// 引入 defineStore，作用是创建一个 store
import { defineStore } from "pinia";

/**
 * Pinia 是 Vue 的状态管理库，是 Vuex 的替代品，专为 Vue 3 设计
 * 
 * Pinia 的主要特点：
 * 1. 类型安全：完全支持 TypeScript
 * 2. 轻量级：体积小，约 1KB
 * 3. 模块化设计：每个 store 都是独立的模块
 * 4. 简单直观：无需创建复杂的模块嵌套
 * 5. 支持 Vue DevTools：可以跟踪 actions、mutations
 * 6. 支持服务端渲染 (SSR)
 * 7. 支持热模块替换 (HMR)
 */

/**
 * defineStore 是创建 store 的核心函数
 * 第一个参数是 store 的唯一 ID，用于 devtools 和 SSR
 * 第二个参数是 store 的配置对象或 setup 函数
 */
export const useCountStore = defineStore("count", {
    // 定义 state, state 是真正存储数据的地方
    // state 必须是一个函数，返回一个对象，这样可以在 SSR 环境中安全使用
    state: () => {
        return {
            count: 0,
            name: "计数器",
            todos: [
                { id: 1, text: "学习 Vue", done: true },
                { id: 2, text: "学习 Pinia", done: false }
            ],
            user: {
                id: 1,
                name: "张三",
                age: 25
            }
        }
    },

    /**
     * getters 类似于 Vue 中的计算属性
     * 可以用来派生状态，或者对状态进行过滤、计算等操作
     * getter 可以访问 state，也可以访问其他 getter
     */
    getters: {
        // 基本 getter，返回 state 的计算结果
        doubleCount: (state) => state.count * 2,

        // 使用 this 访问其他 getter (必须使用普通函数，不能用箭头函数)
        tripleCount() :number{
            return this.doubleCount + this.count;
        },

        // 接收参数的 getter (需要返回一个函数)
        getTodoById: (state) => {
            return (id) => state.todos.find((todo) => todo.id === id);
        },

        // 使用其他 store 的 getter
        otherStoreValue() :number{
            // 可以导入并使用其他 store
            // const otherStore = useOtherStore();
            // return otherStore.someValue + this.count;
            return this.count;
        }
    },

    /**
     * actions 用于定义业务逻辑，类似于 Vuex 中的 mutations 和 actions 的结合
     * actions 可以是异步的，可以包含任意的业务逻辑
     * actions 可以直接修改 state，不需要通过 mutations
     */
    actions: {
        // 基本 action，直接修改 state
        increment(value: number) {
            this.count+= value;
        },

        // 带参数的 action
        incrementBy(amount: number) {
            this.count += amount;
        },

        // 异步 action，可以使用 async/await
        async fetchUserData() {
            try {
                // 模拟 API 请求
                const response = await fetch('https://api.example.com/user');
                const userData = await response.json();
                
                // 更新 state
                this.user = userData;
            } catch (error) {
                console.error('获取用户数据失败:', error);
            }
        },

        // 重置 state 到初始状态
        resetState() {
            // $reset 是 Pinia 提供的内置方法，可以重置 state 到初始值
            this.$reset();
        },

        // 使用其他 store 的 action
        useOtherStoreAction() {
            // 可以导入并使用其他 store 的 action
            // const otherStore = useOtherStore();
            // otherStore.someAction();
            this.increment(1);
        }
    }
});

/**
 * Pinia 的使用方式：
 * 
 * 1. 在组件中使用 store:
 * 
 * <script setup>
 * import { useCountStore } from '@/store/count';
 * 
 * // 初始化 store
 * const countStore = useCountStore();
 * 
 * // 访问 state
 * console.log(countStore.count);
 * 
 * // 修改 state (直接修改)
 * countStore.count++;
 * 
 * // 使用 getter
 * console.log(countStore.doubleCount);
 * 
 * // 调用 action
 * countStore.increment();
 * countStore.incrementBy(10);
 * 
 * // 使用解构，但会失去响应性
 * const { count } = countStore;
 * 
 * // 使用 storeToRefs 保持响应性
 * import { storeToRefs } from 'pinia';
 * const { count, name } = storeToRefs(countStore);
 * </script>
 * 
 * 2. 监听 store 的变化:
 * 
 * import { watch } from 'vue';
 * 
 * // 监听整个 store
 * watch(
 *   countStore,
 *   (newValue, oldValue) => {
 *     console.log('store 变化了', newValue, oldValue);
 *   },
 *   { deep: true }
 * );
 * 
 * // 监听特定的 state
 * watch(
 *   () => countStore.count,
 *   (newCount) => {
 *     console.log('count 变化了', newCount);
 *   }
 * );
 * 
 * 3. 订阅 store 的变化:
 * 
 * // 订阅 state 变化
 * const unsubscribe = countStore.$subscribe(
 *   (mutation, state) => {
 *     console.log('state 变化了', mutation, state);
 *     // 可以持久化到本地存储
 *     localStorage.setItem('counter', JSON.stringify(state));
 *   },
 *   { detached: true } // 组件卸载时不取消订阅
 * );
 * 
 * // 订阅 action
 * const unsubscribeAction = countStore.$onAction(
 *   ({
 *     name, // action 名称
 *     store, // store 实例
 *     args, // 传递给 action 的参数数组
 *     after, // 在 action 返回或解决后的钩子
 *     onError, // action 抛出或拒绝的钩子
 *   }) => {
 *     console.log(`Action ${name} 开始执行`);
 *     
 *     after((result) => {
 *       console.log(`Action ${name} 执行完成，结果:`, result);
 *     });
 *     
 *     onError((error) => {
 *       console.error(`Action ${name} 执行失败:`, error);
 *     });
 *   }
 * );
 * 
 * // 取消订阅
 * unsubscribe();
 * unsubscribeAction();
 */

/**
 * Pinia 的应用场景：
 * 
 * 1. 全局状态管理：
 *    - 用户信息、认证状态
 *    - 应用配置、主题设置
 *    - 全局消息通知
 * 
 * 2. 组件间通信：
 *    - 跨多层组件的数据传递
 *    - 兄弟组件间的数据共享
 * 
 * 3. 数据持久化：
 *    - 结合 localStorage/sessionStorage
 *    - 页面刷新后恢复状态
 * 
 * 4. 表单状态管理：
 *    - 复杂表单的数据管理
 *    - 多步骤表单
 * 
 * 5. 数据缓存：
 *    - API 请求结果缓存
 *    - 避免重复请求
 * 
 * 6. 应用状态同步：
 *    - 多标签页间的状态同步
 *    - 结合 WebSocket 的实时数据更新
 */

/**
 * Pinia 与 Vuex 的区别：
 * 
 * 1. 结构简化：
 *    - Pinia 没有 mutations，直接在 actions 中修改状态
 *    - 不需要嵌套模块，每个 store 都是独立的
 * 
 * 2. TypeScript 支持：
 *    - Pinia 提供更好的类型推断
 *    - 不需要复杂的类型声明
 * 
 * 3. 开发体验：
 *    - 更简洁的 API
 *    - 更好的代码分割
 *    - 更好的自动补全支持
 * 
 * 4. 插件系统：
 *    - 更灵活的插件 API
 *    - 可以扩展 store 的功能
 */
